#include <QMetaProperty>

#include "QRemoteObject2.h"
#include "QRemoteItem.h"


#include "QHierarchyFactory_p.h"

class QObjectHierarchyInterface:public QRemoteObject2::HierarchyInterface
{
public:
    QObjectHierarchyInterface(){

    }

    //设置父级，若设置失败则返回
    virtual bool setParent(QObject* target,QObject* newParent){
        target->setParent(newParent);
        return true;
    }
    //获取父级
    virtual QObject* parent(QObject* target){
        return target->parent();
    }
    //从一个对象中获取父级修改信号
    virtual int parentNotifier(QObject* target){
        //QObject 没有父级通知器
        return -1;
    }
};

class QObjectHierarchyFactory:public QRemoteObject2::HierarchyInterfaceFactory
{
public:

    QRemoteObject2::HierarchyInterface* createInstance(const QMetaObject* meta) override
    {
        return new QObjectHierarchyInterface();
    }
};

//class QWidgetHierarchyInterface:public QRemoteObject2::HierarchyInterface
//{
//public:
//    QWidgetHierarchyInterface(){

//    }

//    //设置父级，若设置失败则返回
//    virtual bool setParent(QObject* target,QObject* newParent){


//    return true;
//    }
//    //获取父级
//    virtual QObject* parent(QObject* target){

//    }
//    //从一个对象中获取父级修改信号
//    virtual int parentNotifier(QObject* target){

//    }
//};

//static HierarchyInterfacePtr qwidgetHierarchyInterface(new QWidgetHierarchyInterface());


class QQuickItemHierarchyInterface:public QRemoteObject2::HierarchyInterface
{
public:
    QQuickItemHierarchyInterface(const QMetaObject* quickMeta)
    {
        meta = quickMeta;
        auto index = meta->indexOfProperty("parent");
        property = meta->property(index);
    }

    //设置父级，若设置失败则返回
    virtual bool setParent(QObject* target,QObject* newParent){

        if(target->metaObject()->inherits(meta) && newParent->metaObject()->inherits(meta))
        {
            property.write(target,QVariant::fromValue(newParent));
            return true;
        }
        return false;
    }
    //获取父级
    virtual QObject* parent(QObject* target){
        return property.read(target).value<QObject*>();
    }
    //从一个对象中获取父级修改信号
    virtual int parentNotifier(QObject* target){
        return property.notifySignalIndex();
    }

private:
    const QMetaObject* meta;
    QMetaProperty property;
};

class QQuickItemHierarchyFactory:public QRemoteObject2::HierarchyInterfaceFactory
{
public:

    QRemoteObject2::HierarchyInterface* createInstance(const QMetaObject* meta) override
    {
        return new QQuickItemHierarchyInterface(meta);
    }
};

class QNodeHierarchyInterface:public QRemoteObject2::HierarchyInterface
{
public:
    QNodeHierarchyInterface(const QMetaObject* quickMeta)
    {
        meta = quickMeta;
        auto index = meta->indexOfProperty("parent");
        property = meta->property(index);
    }
    //设置父级，若设置失败则返回
    virtual bool setParent(QObject* target,QObject* newParent){

        if(target->metaObject()->inherits(meta) && newParent->metaObject()->inherits(meta))
        {
            property.write(target,QVariant::fromValue(newParent));
            return true;
        }
        return false;
    }
    //获取父级
    virtual QObject* parent(QObject* target){
        return property.read(target).value<QObject*>();
    }
    //从一个对象中获取父级修改信号
    virtual int parentNotifier(QObject* target){
        return property.notifySignalIndex();
    }

private:
    const QMetaObject* meta;
    QMetaProperty property;
};

class QNodeHierarchyFactory:public QRemoteObject2::HierarchyInterfaceFactory
{
public:

    QRemoteObject2::HierarchyInterface* createInstance(const QMetaObject* meta) override
    {
        return new QNodeHierarchyInterface(meta);
    }
};

class QRemoteItemHierarchyInterface:public QRemoteObject2::HierarchyInterface
{
public:
    QRemoteItemHierarchyInterface()
    {
        notifySignal = QRemoteItem::staticMetaObject.indexOfSignal("parentChanged(QRemoteItem*)");
    }

    //设置父级，若设置失败则返回
    virtual bool setParent(QObject* target,QObject* newParent){
        auto that = qobject_cast<QRemoteItem*>(target);
        auto thatParent = qobject_cast<QRemoteItem*>(newParent);

        if(!newParent && thatParent) return false;

        if(that)
        {
            that->setParent(thatParent);
            return true;
        }
        return false;
    }
    //获取父级
    virtual QObject* parent(QObject* target){
        auto that = qobject_cast<QRemoteItem*>(target);
        if(that)
        {
            return that->parent();
        }
        return NULL;
    }
    //从一个对象中获取父级修改信号
    virtual int parentNotifier(QObject* target){
        return notifySignal;
    }

private:
    int notifySignal;
};

class QRemoteItemHierarchyFactory:public QRemoteObject2::HierarchyInterfaceFactory
{
public:

    QRemoteObject2::HierarchyInterface* createInstance(const QMetaObject* meta) override
    {
        return new QRemoteItemHierarchyInterface();
    }
};

static void registerHierarcyFactory(){
    QRemoteObject2::registerHierarchyFactory("QObject",new QObjectHierarchyFactory());
    QRemoteObject2::registerHierarchyFactory("QQuickItem",new QQuickItemHierarchyFactory());
    QRemoteObject2::registerHierarchyFactory("Qt3DCore::QNode",new QNodeHierarchyFactory());
    QRemoteObject2::registerHierarchyFactory("QRemoteItem",new QRemoteItemHierarchyFactory());
}



QHierarchtFactoryManager *QHierarchtFactoryManager::Instance()
{
    static QHierarchtFactoryManager instance;
    return &instance;
}

void QHierarchtFactoryManager::registerHierarchyFactory(const char *className, QRemoteObject2::HierarchyInterfaceFactory *factory)
{
    QMutexLocker locker(&m_HierarchyInterfaceFactoryMutex);

    m_HierarchyInterfaceFactorys[className].reset(factory);
}

QRemoteObject2::HierarchyInterfaceFactory* QHierarchtFactoryManager::getHierarchyFactory(const char *className)
{
    QMutexLocker locker(&m_HierarchyInterfaceFactoryMutex);

    return m_HierarchyInterfaceFactorys.value(QString::fromLocal8Bit(className)).get();
}

QRemoteObject2::HierarchyInterfaceFactory *QHierarchtFactoryManager::findHierarchyFactory(const QMetaObject* meta)
{
    QMutexLocker locker(&m_HierarchyInterfaceFactoryMutex);

    auto tempMeta = meta;

    while (tempMeta) {
        auto factory = m_HierarchyInterfaceFactorys.value(tempMeta->className());
        if(factory)
        {
            return factory.get();
        }

        tempMeta = tempMeta->superClass();
    }

    return NULL;
}

Q_CONSTRUCTOR_FUNCTION(registerHierarcyFactory)
